﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ASoft.Service;
using System.Runtime.Serialization;

namespace ASoft.Msg
{
    [DataContract]
    public abstract class MsgBase
    {


        public MsgBase()
        {

        }

        public MsgBase(Byte[] data)
        {
            MsgFactory.GetMsgAttribute(this.GetType()).Check(data);
            this.MsgData = data;
            LoadFromData(data);
        }

        Byte[] _MsgData;
        protected Byte[] MsgData
        {
            get
            {
                if (_MsgData == null)
                {
                    _MsgData = new byte[帧长];
                    _MsgData[0] = 帧头;
                    _MsgData[1] = 帧长;
                    _MsgData[帧长 - 1] = 检验字节;
                }
                return _MsgData;
            }
            set
            {
                _MsgData = value;
            }
        }

        public byte 帧头
        {
            get
            {
                return MsgFactory.GetMsgAttribute(this.GetType()).帧头;
            }
        }

        public byte 帧长
        {
            get
            {
                return MsgFactory.GetMsgAttribute(this.GetType()).帧长;
            }
        }
        public byte 检验字节
        {
            get
            {
                return MsgFactory.GetMsgAttribute(this.GetType()).检验字节;
            }
        }

        public byte[] GetData()
        {
            SetToData(MsgData);
            return MsgData;
        }

        protected void SetToData(byte[] data)
        {
            this.GetType()
                .GetProperties()
                .ToList()
                .ForEach(p =>
                    {
                        var sp = p.GetCustomAttributes(typeof(SPAttribute), true).FirstOrDefault() as SPAttribute;
                        if (sp != null)
                        {
                            //处理灌溉加湿电磁阀湿度确认时间
                            if (p.PropertyType.Equals(typeof(short)))
                            {
                                data[sp.Order - 1] = (byte)(short)p.GetValue(this, null);
                            }
                            else
                            {
                                data[sp.Order - 1] = (byte)p.GetValue(this, null);
                            }
                            return;
                        }

                        var dp = p.GetCustomAttributes(typeof(DPAttribute), true).FirstOrDefault() as DPAttribute;
                        if (dp != null)
                        {
                            var value = (short)p.GetValue(this, null);
                            data[dp.LowOrder - 1] = ConvertUtility.GetLow(value);
                            data[dp.HightOrder - 1] = ConvertUtility.GetHight(value);
                        }
                    });
        }

        protected void LoadFromData(byte[] data)
        {
            this.GetType()
                .GetProperties()
                .ToList()
                .ForEach(p =>
                {
                    var sp = p.GetCustomAttributes(typeof(SPAttribute), true).FirstOrDefault() as SPAttribute;
                    if (sp != null && !sp.OnlyRead)
                    {
                        p.SetValue(this, data[sp.Order - 1], null);
                        return;
                    }

                    var dp = p.GetCustomAttributes(typeof(DPAttribute), true).FirstOrDefault() as DPAttribute;
                    if (dp != null && !dp.OnlyRead)
                    {
                        var value = ConvertUtility.GetShort(data[dp.HightOrder - 1], data[dp.LowOrder - 1]);
                        p.SetValue(this, value, null);
                    }
                });
        }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }
}
